
#include "JniObject.h"
#include <stdlib.h>

// 运行在main函数之前。。尽量少调new或stl里的东西。所以用了数组。
class ObjectFactoryHelper {
public:
    char                className[1024];
    JniObjectFactory*   factory;
};

class NativeMethodRegisterHelper {
public:
    char    className[1024];
    lpfnRegisterNativeMethods method;
};

static ObjectFactoryHelper g_objectfactories[100] = {{{0}, NULL}};
static int  g_max_factories = 0;

static NativeMethodRegisterHelper   g_nativemethods_procedure[100] = {{{0}, NULL}};
static int  g_max_native_methods = 0;

JniObject* JniObjectFactory::createByClassName(const char * name)
{
    int i;
    for (i = 0; i < g_max_factories; i++) {
        if (strcmp(g_objectfactories[i].className, name) == 0) {
            if (g_objectfactories[i].factory != NULL)
                return g_objectfactories[i].factory->doCreate();
        }
    }
    return NULL;
}

void JniObjectFactory::reg(const char * name)
{
    printf("register creator for class: %s\n", name);
    int i;
    for (i = 0; i < g_max_factories; i++) {
        if (g_objectfactories[i].className[0] == '\0') {
            strncpy(g_objectfactories[i].className, name, sizeof(ObjectFactoryHelper::className));
            break;
        }
    }
    if (i >= g_max_factories) {
        if (g_max_factories >= (int)(sizeof(g_objectfactories) / sizeof(g_objectfactories[0]))) {
            // 太多了。满了。
            abort();
        } else {
            strncpy(g_objectfactories[g_max_factories].className, name, sizeof(ObjectFactoryHelper::className));
            g_objectfactories[g_max_factories].factory = this;
            g_max_factories++;
        }
    }
}

void JniObjectFactory::unreg()
{
    int i;
    for (i = 0; i < g_max_factories; i++) {
        if (g_objectfactories[i].factory == this) {
            g_objectfactories[i].className[0] = '\0';
        }
    }
}

// 注册本地方法。
JniObjectNativeMethodHelper::JniObjectNativeMethodHelper(lpfnRegisterNativeMethods func, const char * className)
{
    if (g_max_native_methods >= (int)(sizeof(g_nativemethods_procedure) / sizeof(g_nativemethods_procedure[0]))) {
        abort();
    } else {
        // printf("save native methods for class: %s\n", className);
        strncpy(g_nativemethods_procedure[g_max_native_methods].className, className, sizeof(NativeMethodRegisterHelper::className));
        g_nativemethods_procedure[g_max_native_methods].method = func;

        JniObject::alterClassName(g_nativemethods_procedure[g_max_native_methods].className);
        g_max_native_methods++;
    }
}

void JniObjectNativeMethodHelper::RegisterAllNatives(JNIEnv* env)
{
    int i;
    for (i = 0; i < g_max_native_methods; i++) {
        if (g_nativemethods_procedure[i].method) {
            // printf("register for class: %s\n", g_nativemethods_procedure[i].className);
            jclass clazz = (jclass)env->FindClass(g_nativemethods_procedure[i].className);
            // printf("env = %p, clazz = %p\n", env, clazz);
            if (clazz != NULL)
                g_nativemethods_procedure[i].method(env, clazz);
        }
    }
}


#if 0
class LinkNode {
public:
    std::string     className;
    JniObjectFactory*  factory;
    LinkNode*       prev;
    static LinkNode* tail;

    LinkNode() : factory(NULL), prev(NULL) {}
    LinkNode(const char * n, JniObjectFactory* f)
        : className(n)
          , factory(f)
          , prev(tail)
    {
        tail = this;
    }

    static LinkNode* find(const char * className) {
        LinkNode* node = tail;
        while (node != NULL) {
            if (node->className == className) {
                return node;
            }
            node = node->prev;
        }
        return NULL;
    }
    static void remove(JniObjectFactory* f) {
        LinkNode* node = tail;
        LinkNode* temp = node;
        while (node != NULL) {
            if (node->factory == f) {
                if (node != tail) {
                    temp->prev = node->prev;
                } else {
                    tail = node->prev;
                    temp = tail;
                }
                delete node;
                node = temp;
            }
            temp = node;
            if (node == NULL)
                break;
            node = node->prev;
        }
    }
};

LinkNode* LinkNode::tail = NULL;

JniObjectFactory::~JniObjectFactory()
{
    unreg();
}

JniObject* JniObjectFactory::createByClassName(const char * name)
{
    LinkNode* node = LinkNode::find(name);
    if (node != NULL) {
        if (node->factory != NULL)
            return node->factory->doCreate();
    }
    return NULL;
}

void JniObjectFactory::reg(const char * name)
{
    new LinkNode(name, this);
}

void JniObjectFactory::unreg()
{
    LinkNode::remove(this);
}
#endif

